/*
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.drawee.view;

import java.util.ArrayList;

import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import android.view.View;

import com.facebook.common.internal.Lists;
import com.facebook.common.internal.Preconditions;
import com.facebook.common.internal.VisibleForTesting;
import com.facebook.drawee.interfaces.DraweeHierarchy;

/**
 * Contains multiple Drawee holders.
 * <p/>
 * <p>Intended for use in custom views that are showing more than one hierarchy.
 * <p/>
 * Users of this class must< call {@link Drawable#setBounds} on the top-level drawable
 * of each DraweeHierarchy in this holder. Otherwise the drawables will not be drawn.
 * <p/>
 * <p>The containing view must also call {@link #onDetach()} from its
 * {@link View#onStartTemporaryDetach()} and {@link View#onDetachedFromWindow()} methods. It must
 * call {@link #onAttach} from its  {@link View#onFinishTemporaryDetach()} and
 * {@link View#onAttachedToWindow()} methods.
 */
public class MultiDraweeHolder<DH extends DraweeHierarchy> {

    @VisibleForTesting
    boolean mIsAttached = false;
    @VisibleForTesting
    ArrayList<DraweeHolder<DH>> mHolders = Lists.newArrayList();

    /**
     * Gets the controller ready to display the images.
     * <p/>
     * <p>The containing view must call this method from both {@link View#onFinishTemporaryDetach()}
     * and {@link View#onAttachedToWindow()}.
     */
    public void onAttach() {
        if (mIsAttached) {
            return;
        }
        mIsAttached = true;
        for (int i = 0; i < mHolders.size(); ++i) {
            mHolders.get(i).onAttach();
        }
    }

    /**
     * Releases resources used to display the image.
     * <p/>
     * <p>The containing view must call this method from both {@link View#onStartTemporaryDetach()}
     * and {@link View#onDetachedFromWindow()}.
     */
    public void onDetach() {
        if (!mIsAttached) {
            return;
        }
        mIsAttached = false;
        for (int i = 0; i < mHolders.size(); ++i) {
            mHolders.get(i).onDetach();
        }
    }

    public boolean onTouchEvent(MotionEvent event) {
        for (int i = 0; i < mHolders.size(); ++i) {
            if (mHolders.get(i).onTouchEvent(event)) {
                return true;
            }
        }
        return false;
    }

    public void clear() {
        if (mIsAttached) {
            for (int i = 0; i < mHolders.size(); ++i) {
                mHolders.get(i).onDetach();
            }
        }
        mHolders.clear();
    }

    public void add(DraweeHolder<DH> holder) {
        add(mHolders.size(), holder);
    }

    public void add(int index, DraweeHolder<DH> holder) {
        Preconditions.checkNotNull(holder);
        Preconditions.checkElementIndex(index, mHolders.size() + 1);
        mHolders.add(index, holder);
        if (mIsAttached) {
            holder.onAttach();
        }
    }

    public void remove(int index) {
        DraweeHolder<DH> holder = mHolders.get(index);
        if (mIsAttached) {
            holder.onDetach();
        }
        mHolders.remove(index);
    }

    public DraweeHolder<DH> get(int index) {
        return mHolders.get(index);
    }

    public int size() {
        return mHolders.size();
    }

    /**
     * Convenience method to draw all the top-level drawables in this holder.
     */
    public void draw(Canvas canvas) {
        for (int i = 0; i < mHolders.size(); ++i) {
            Drawable drawable = get(i).getTopLevelDrawable();
            if (drawable != null) {
                drawable.draw(canvas);
            }
        }
    }

    /**
     * Returns true if the argument is a top-level Drawable in this holder.
     */
    public boolean verifyDrawable(Drawable who) {
        for (int i = 0; i < mHolders.size(); ++i) {
            if (who == get(i).getTopLevelDrawable()) {
                return true;
            }
        }
        return false;
    }
}
